// server.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h> 
#include <stdio.h>
#include <conio.h>
#include <tchar.h>

#include <strsafe.h>
#include "msg.h"
#include "bus.h"
#include "win-util.h"






DWORD WINAPI InstanceThread(LPVOID); 
VOID GetAnswerToRequest(LPTSTR, LPTSTR, LPDWORD); 
 

 
int _tmain(int argc, LPCTSTR argv[]) 
{ 


   BOOL   fConnected = FALSE; 
   DWORD  dwThreadId = 0; 
   HANDLE hPipe = INVALID_HANDLE_VALUE, hThread = NULL; 
   LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe"); 
	int board_init();

   if(board_init()<0)
   {

	  _tprintf( TEXT("\nsystem initialization failed.\n"));
	  return 1;
   }
 
	int TTYStart(LPCTSTR  argv0);

	TTYStart(argv[0]);



// The main loop creates an instance of the named pipe and 
// then waits for a client to connect to it. When the client 
// connects, a thread is created to handle communications 
// with that client, and this loop is free to wait for the
// next client connect request. It is an infinite loop.

  hPipe = CreateNamedPipe( 
      lpszPipename,             // pipe name 
      PIPE_ACCESS_DUPLEX,       // read/write access 
      PIPE_TYPE_MESSAGE |       // message type pipe 
      PIPE_READMODE_MESSAGE |   // message-read mode 
      PIPE_WAIT,                // blocking mode 
      PIPE_UNLIMITED_INSTANCES, // max. instances  
      BUFSIZE,                  // output buffer size 
      BUFSIZE,                  // input buffer size 
      0,                        // client time-out 
      NULL);                    // default security attribute 

  if (hPipe == INVALID_HANDLE_VALUE) 
  {
      _tprintf(TEXT("CreateNamedPipe failed, GLE=%d.\n"), GetLastError()); 
	  LastErrorMsg();
      return -1;
  }
  _tprintf( TEXT("\nPipe Server: Main thread awaiting client connection on %s\n"), lpszPipename);
  for(;;)
  {
      // Wait for the client to connect; if it succeeds, 
      // the function returns a nonzero value. If the function
      // returns zero, GetLastError returns ERROR_PIPE_CONNECTED. 
 
      fConnected = ConnectNamedPipe(hPipe, NULL) ? 
         TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); 
 
      if (fConnected) 
      { 
          _tprintf( TEXT("Client connected, creating a processing thread.\n")); 
		 
	  }

	  //
	  //msg loop
	  //

	   int pipe_msg_loop(HANDLE hPipe);
	   pipe_msg_loop(hPipe);
	   DisconnectNamedPipe(hPipe); 

	   if(_kbhit()&&_getch()==' ') break;
  }

   CloseHandle(hPipe); 
   
	CloseHandle(hThread);
	//void log_close();
	//log_close();
	//void floppy_unmount(int index);
	//floppy_unmount(0);
	//void ide_unmount(int index);
	//ide_unmount(0);
	//bool save_cmos();
	//save_cmos();
   return 0; 
} 
 
int pipe_msg_loop(HANDLE hPipe)
{
   BOOL   fSuccess = FALSE; 
   DWORD cbBytesRead,cbWritten;
   char buffer[BUFSIZE];


// Loop until done reading
   while (1) 
   { 
#ifdef DEBUG 
	   _tprintf(TEXT("\nInstanceThread: read request.\n"));
#endif
   // Read client requests from the pipe. This simplistic code only allows messages
   // up to BUFSIZE characters in length.
      fSuccess = ReadFile( 
         hPipe,        // handle to pipe 
         buffer,    // buffer to receive data 
         BUFSIZE, // size of buffer 
         &cbBytesRead, // number of bytes read 
         NULL);        // not overlapped I/O 

      if (!fSuccess || cbBytesRead == 0)
      {   
          if (GetLastError() == ERROR_BROKEN_PIPE)
          {
              _tprintf(TEXT("InstanceThread: client disconnected.\n"), GetLastError()); 
			  break;
          }
          else
          {
              _tprintf(TEXT("InstanceThread ReadFile failed, GLE=%d.\n"), GetLastError()); 
			  break;
          }
          
      }

   // Process the incoming message.

	  void process_msg(char *buffer);



	  PIPE_MSG *msg=(PIPE_MSG *)buffer;
#ifdef DEBUG       
	 _tprintf(TEXT("message received.(%x)\n"),cbBytesRead);
	 for(int i=0;i<cbBytesRead;i++) printf("%02x ",(unsigned char)buffer[i]);
	 _tprintf(TEXT("\n"));
#endif
	  process_msg(buffer);

   // Write the reply to the pipe. 
      fSuccess = WriteFile( 
         hPipe,        // handle to pipe 
         buffer,     // buffer to write from 
         msg->hdr.size, // number of bytes to write 
         &cbWritten,   // number of bytes written 
         NULL);        // not overlapped I/O 

      if (!fSuccess || msg->hdr.size != cbWritten)
      {   
          _tprintf(TEXT("InstanceThread WriteFile failed, GLE=%d.\n"), GetLastError()); 
          break;
      }
	   FlushFileBuffers(hPipe); 
#ifdef DEBUG 
	 _tprintf(TEXT("\nreply sent.(%x)\n"),cbWritten);
	 for(int i=0;i<cbWritten;i++) printf("%02x ",(unsigned char)buffer[i]);
#endif
  }

// Flush the pipe to allow the client to read the pipe's contents 
// before disconnecting. Then disconnect the pipe, and close the 
// handle to this pipe instance. 
 




    _tprintf( TEXT("InstanceThread exitting.\n"));



   return 1;
}



DWORD WINAPI msg_thread( LPVOID lpParam );




void process_msg(char *buffer)
{ 
	PIPE_MSG *msg=(PIPE_MSG *)buffer;
	char cbReplyBytes;
	char n;
	char *p;
	unsigned int address;

	int off;

	switch(msg->hdr.type)
	{
	case MREAD :
		  cbReplyBytes=msg->hdr.count;
#ifdef DEBUG 
			printf("MREAD:%x,%x\n",msg->u.mread.address_lo,msg->hdr.count);
#endif
			p=buffer+SIZE_REPLY;
			address=msg->u.mread.address_lo;

			n=msg->hdr.count;
			while(n>3)
			{
			*(int*)p=bus_read_int(address);
			//printf("%x:%x\n",address,*(int*)p);
			address+=4;
			p+=4;
			n-=4;
			}
			while(n>1)
			{
			*(short*)p=bus_read_short(address);
			address+=2;
			n-=2;
			p+=2;
			}
			if(n) *p=bus_read_byte(address);
			break;
	case MWRITE :
#ifdef DEBUG 
			printf("MWRITE:%x,%x\n",msg->u.mread.address_lo,msg->hdr.count);
#endif
			p=buffer+SIZE_MWRITE;
			address=msg->u.mwrite.address_lo;

			n=msg->hdr.count;
			while(n>3)
			{
			bus_write_int(address,*(int*)p);
			address+=4;
			p+=4;
			n-=4;
			}
			while(n>1)
			{
			bus_write_short(address,*(short*)p);
			address+=2;
			p+=2;
			n-=2;
			}
			if(n) bus_write_byte(address,*p);
#ifdef DEBUG 
			for(int i=0;i<msg->hdr.count;i++) printf("%02x ",(unsigned char)buffer[SIZE_MWRITE+i]);
#endif
			cbReplyBytes=0;
			break;
	case MWRITEBE :
#ifdef DEBUG 
			printf("MWRITEBE:%x,%x\n",msg->u.mwrite.address_lo,msg->hdr.be);
#endif
			n=0;
			off=0;
			while(n<8)
			{
				if(n<4&&msg->hdr.be&(0xf<<n))
				{
					bus_write_int(msg->u.mread.address_lo+off,*(int *)&buffer[SIZE_MWRITE+off]);
					off+=4;
					n+=4;
				}
				else if(n<7&&msg->hdr.be&(0x3<<n))
				{
					bus_write_short(msg->u.mread.address_lo+off,*(short *)&buffer[SIZE_MWRITE+off]);
					off+=2;
					n+=2;
				}
				else if(n<8&&msg->hdr.be&(0x1<<n))
				{
					bus_write_byte(msg->u.mread.address_lo+off,buffer[SIZE_MWRITE+off]);
					off++;
					n++;
				}else
				{
					off++;
					n++;
				}
			}
#ifdef DEBUG 
			for(int i=0;i<msg->hdr.count;i++) printf("%02x ",(unsigned char)buffer[SIZE_MWRITE+i]);
#endif
		    cbReplyBytes=0;

			break;
	case INTA :
#ifdef DEBUG 
			printf("INTA");
#endif
			cbReplyBytes=0;
			break;

	case REPLY :
#ifdef DEBUG 
			printf("REPLY");
#endif

			break;

	  }
 
	  msg->hdr.type=REPLY;
	  msg->hdr.count=(unsigned char)cbReplyBytes; 
      msg->hdr.size=cbReplyBytes+SIZE_REPLY;
}